#include "./include/client.h"
#include <time.h>
#define buf_len 65535
const double CLOCKS_PER_SECOND = ((clock_t)1000);
const double CLOCKS_PER_MILLISECOND = ((clock_t)1);
Client::Client()
{
    _sockfd = -1;
}

Client::~Client()
{
    if (_sockfd != -1)
    {
        close(_sockfd);
    }
}

int Client::recvn(int fd, string &s_recv, int length)
{
    // ...
    int total = 0; // 记录已经收到的数据的长度
    char buf[buf_len];
    while (total < length)
    {
        int read_len = length - total;
        if (read_len >= buf_len)
            read_len = buf_len - 1;
        ssize_t sret = recv(fd, buf, read_len, 0);
        total += sret;
        *(buf + sret) = '\0';
        s_recv += (string)buf;
    }
    return total;
}

int Client::clientTcpInit(const char *ip, const char *port)
{
    // ...
    _sockfd = socket(AF_INET, SOCK_STREAM, 0); // ipv4 tcp
    struct sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(atoi(port));
    serverAddr.sin_addr.s_addr = inet_addr(ip);
    int ret = connect(_sockfd, (struct sockaddr *)&serverAddr, sizeof(struct sockaddr_in));
    ERROR_CHECK(ret, -1, "connect");
    return 0;
}

int Client::sendTrain(json &ptrain)
{
    // ...
    string s_send = ptrain.dump();
    int len = s_send.length();

    send(_sockfd, &len, sizeof(int), 0);
    //cout << "send_len=" << len << endl;
    //cout << "s_send= " << s_send << endl;
    int sret = send(_sockfd, s_send.c_str(), s_send.size(), 0);
    return 0;
}

int Client::recvTrain(json &ptrain)
{
    // ...
    int len;
    recv(_sockfd, &len, sizeof(int), 0);
    //cout << "recv_len=" << len << endl;
    string s_recv;
    //cout << "s_recv:" << endl
    //<< s_recv << endl;
    int sret = recvn(_sockfd, s_recv, len);
    ptrain = json::parse(s_recv);
    return 0;
}

void Client::clientCmd()
{
    // ...
    // 用于建立连接后用户循环输入命令进行交互
    string s_send, s_recv; // 用户输入数组
    cli_msg msg_send;      // 注意cli_msg和ser_msg
    ser_msg msg_recv;
    json json_send, json_recv;
    while (1)
    {
        // 第一次输入关键词，得到服务器的相关关键字
        //  fflush(stdout);
        int flag = 0;
        while (!flag)
        {
            cout << "-------------------------------------------" << endl;
            cout << "input 1 for key words, 2 for pages" << endl;
            string s;
            getline(cin, s);
            // 用户的需求选择
            msg_send.msgid = atoi(s.c_str());

            if (1 == msg_send.msgid || 2 == msg_send.msgid)
                flag = 1;
        }

        cout << "input search words:" << endl;
        // 用户输入的一行string
        getline(cin, msg_send.data);
        // 把msg_send转换为json格式
        cli_to_json(json_send, msg_send);

        // json通过标签"data"拿到{"data", m.data}中的 m.data
        
        //cout << "json_send[\"data\"]= " << json_send["data"] << endl;

        // 发送转换后的json格式
        sendTrain(json_send);
        // clock_t start_time=clock();
        // timespec time_start = {0, 0};
        // timespec time_end = {0, 0};
        // clock_gettime(CLOCK_REALTIME, &time_start);

        //cout << endl
             //<< "send_ok" << endl;
        // 等待接收服务端返回的json数据
        recvTrain(json_recv);
        // clock_t stop_time=clock();
        // cout<<"搜索用时: "<<(stop_time-start_time)/CLOCKS_PER_SECOND<<"S "
        // <<(stop_time-start_time)/CLOCKS_PER_MILLISECOND<<"MS"<<endl;
        //clock_gettime(CLOCK_REALTIME, &time_end);
        // cout<<"搜索用时:"<<(time_end.tv_nsec-time_start.tv_nsec)/1000000<<"ms"<<endl;
        // double search_time = (time_end.tv_nsec - time_start.tv_nsec) / 1000000;
        // if (search_time < 0)
        // {
        //     search_time += 1;
        // }
        // printf("搜索用时=%f ms\n", search_time);

        // if (time_end.tv_sec < time_start.tv_sec)
        // {
        //     time_end.tv_sec += 1;
        // }
        // double search_time = (time_end.tv_sec - time_start.tv_sec) * 1000.0 + (time_end.tv_nsec - time_start.tv_nsec) / 1000000.0;
        // printf("搜索用时=%f ms\n", search_time);
       
        // time_start.tv_sec = 0;
        // time_end.tv_sec = 0;
        // cout<<"搜索用时: "<<(stop_time-start_time)/CLOCKS_PER_MILLISECOND<<"MS"<<endl;

        //  把json_recv的数据传到msg_recv
        ser_from_json(json_recv, msg_recv);

        // 定义msgid=200是服务2：推荐网页发送过来的数据
        if (200 == msg_recv.msgid)
        {
            cout << "-------------------------------------------" << endl;
            cout << "网页搜索结果：" << endl;
            int msg_recv_datasize = msg_recv.data.size();
            // 如果搜索的页面有推荐，有匹配到的网页
            if (msg_recv_datasize)
            {
                // 如果推荐到的网页少于5条，vector<string>中string的格式
                if (msg_recv_datasize < 5)
                {
                    for (auto &elem : msg_recv.data)
                    {

                        // 这里需要拆包函数？不需要，服务端已经打包输出的格式
                        // string stmp;
                        // // cout<<endl;
                        // stmp += "id=";
                        // char ctmp[20] = {0};
                        // sprintf(ctmp, "%d\n", _pageLib[elem.first].getDocId());
                        // stmp += ctmp;
                        // // cout<<"id="<<_pageLib[elem.first].getDocId()<<endl;
                        // stmp += "Title=" + _pageLib[elem.first].getTitle() + '\n';
                        // // cout<<"Title="<<_pageLib[elem.first].getTitle()<<endl;
                        // stmp += "URL=" + _pageLib[elem.first].getURL() + '\n';
                        // // cout<<"URL="<<_pageLib[elem.first].getURL()<<endl;
                        // stmp += "摘要=" + _pageLib[elem.first].getSummary() + '\n';
                        // vec_result.push_back(stmp);

                        cout << elem << endl;
                    }
                    cout << "共计" << msg_recv_datasize << "条符合要求的网页" << endl;
                }
                // 如果推荐到的网页多于5条，需要分页，vector<string>中string的格式
                else
                {
                    for (int i = 0; i < 5; ++i)
                    {
                        // 服务端已经打包输出格式
                        cout << msg_recv.data[i] << endl;
                    }

                    cout << "以上为前五条网页" << endl;

                    int pagenumber = 1;
                    // 分页逻辑
                    while (1)
                    {
                        flag = 0;
                        while (!flag)
                        {
                            cout << " 共有" << msg_recv_datasize / 5 << "页。" << endl;
                            cout << "当前为" << pagenumber << "页" << endl;
                            cout << "请输入想要查看的页码，退出请输入-1。" << endl;

                            // 输入像查看的页码
                            string s;
                            getline(cin, s);
                            int pagetmp = 0;
                            pagetmp = atoi(s.c_str());

                            // 判断输入的页码是否合法，当合法时才跳出while
                            if (pagetmp == -1 || (1 <= pagetmp && pagetmp <= msg_recv_datasize / 5))
                            {
                                flag = 1;
                                // 记录合法的页码 或者-1表示退出本次查询
                                pagenumber = pagetmp;
                            }
                        }
                        //-1表示退出本次查询，再次选择业务1或者业务2
                        if (pagenumber == -1)
                            break;
                        // 注意最后一页的边界条件 ，还有一个小bug 如果刚好有六页，最后一页将无法输出
                        if (pagenumber == msg_recv_datasize / 5)
                        {
                            for (int i = msg_recv_datasize - 5 - 1; i < msg_recv_datasize - 1; ++i)
                            {
                                // 服务端已经打包输出格式
                                cout << msg_recv.data[i] << endl;
                            }
                        }
                        // 中间的页某5页
                        else
                        {
                            for (int i = (pagenumber - 1) * 5; i < pagenumber * 5; ++i)
                            {
                                // 服务端已经打包输出格式
                                cout << msg_recv.data[i] << endl;
                            }
                        }
                    }
                }
            }
            // 没有匹配的网页
            else
                cout << "no result" << endl;
        }

        // 定义msgid=100是服务1：关键词推荐发送过来的数据
        else if (100 == msg_recv.msgid)
        {
            cout << "-------------------------------------------" << endl;
            cout << "关键字搜索结果" << endl;
            if (msg_recv.data.size())
            {
                for (auto &elem : msg_recv.data)
                {
                    /*
                    服务端关键字tui 已经打包输出格式如下
                    KeyRecommander::mergeVectors（）输出格式打包函数

                    for (size_t i = 0; i < maxSubVectorSize; ++i)
                    {
                        std::string mergedStr;
                        for (const auto &vec : vectors)
                        {
                            if (i < vec.size())
                            {
                                mergedStr += vec[i] + " ";
                            }
                        }
                        if (!mergedStr.empty())
                            mergedStr.pop_back(); // 移除最后一个空格字符
                        _mergedVector.push_back(mergedStr);
                    }
                    */
                    cout << elem << endl;
                }
            }
            else
                cout << "no result" << endl;
        }
        //
        else
        {
            cout << "illegal mesage" << endl;
            continue;
        }

        // cout<<msg_recv.data<<endl;
        // 获取相关关键字后，发送查询关键字给服务器，等到收到相关网页
    }
}

void Client::start(const char *ip, const char *port)
{
    clientTcpInit(ip, port);
    clientCmd();
}

int main(int argc, char *argv[])
{
    ARGS_CHECK(argc, 3);
    // ./client 127.0.0.1 8888
    Client client;
    client.start(argv[1], argv[2]);
    return 0;
}
